﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Consul;
using Dralee.ConsulRegister.Models;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace Dralee.ConsulRegister.Services
{
    public class RegisterServices : IHostedService
    {
        private readonly ILogger _logger;
        private readonly ConsulService _consulService;
        private readonly HealthService _healthService;
        private readonly IApplicationLifetime _applicationLifetime;

        public RegisterServices(ILoggerFactory loggerFactory, IOptions<ConsulService> options,
            IOptions<HealthService> heaOptions, IApplicationLifetime applicationLifetime)
        {
            _logger = loggerFactory.CreateLogger<RegisterServices>();
            _consulService = options.Value;
            _healthService = heaOptions.Value;
            _applicationLifetime = applicationLifetime;
        }

        public Task StopAsync(CancellationToken cancellationToken)
        {
            _logger.LogInformation($"Register Center is stopped.");
            return Task.CompletedTask;
        }

        public Task StartAsync(CancellationToken cancellationToken)
        {
            _logger.LogInformation($"Register Center is starting...");
            Register();
            return Task.CompletedTask;
        }

        protected async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                _logger.LogInformation($"Register Center is working. {_consulService.IP}:{_consulService.Port}");
                await Task.Delay(TimeSpan.FromSeconds(1000), stoppingToken);
            }
        }

        private void Register()
        {
            var consulClient = new ConsulClient(x => x.Address = new Uri($"http://{_consulService.IP}:{_consulService.Port}"));// 请求注册的consul地址
            foreach (var serviceItem in _healthService.ServiceItems)
            {
                var httpCheck = new AgentServiceCheck()
                {
                    DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5), // 服务启动多久后注册
                    Interval = TimeSpan.FromSeconds(10), // 健康检查时间间隔，心跳间隔
                    HTTP = $"http://{serviceItem.Ip}:{serviceItem.Port}/api/health", // 健康检查地址
                    Timeout = TimeSpan.FromSeconds(5)
                };
                // Register service with consul
                var registration = new AgentServiceRegistration
                {
                    Checks = new[] { httpCheck },
                    ID = serviceItem.Name + "_" + serviceItem.Port,
                    Name = serviceItem.Name,
                    Address = serviceItem.Ip,
                    Port = serviceItem.Port,
                    Tags = new[] { $"urlprefix-/{serviceItem.Name}" } // 添加urlprefix-/serviceName 格式tag标签，以便Fabio识别
                };
                consulClient.Agent.ServiceRegister(registration).Wait(); // 服务注册时注册，内部实现其实就是使用consul api进行注册 httpClient发起
                _applicationLifetime.ApplicationStopping.Register(() =>
                {
                    consulClient.Agent.ServiceDeregister(registration.ID).Wait(); // 服务停止时取消注册
                });
            }

        }
    }
}
